/**
 * 验证电子邮箱格式
 * @param value 待验证的邮箱字符串
 * @returns 是否符合邮箱格式
 */
function email(value : string) : boolean {
	return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value);
}

/**
 * 验证手机格式
 * @param value 待验证的手机号字符串
 * @returns 是否符合手机号格式
 */
function mobile(value : string) : boolean {
	return /^1([3589]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value);
}

/**
 * 验证URL格式
 * @param value 待验证的URL字符串
 * @returns 是否符合URL格式
 */
function url(value : string) : boolean {
	return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/.test(value);
}

/**
 * 验证日期格式
 * @param value 待验证的日期（字符串、时间戳或Date对象）
 * @returns 是否为有效日期
 */
function date(value : string | number | Date) : boolean {
	if (!value) return false;

	// 处理Date对象的情况
	if (value instanceof Date) {
		return !isNaN(value.getTime());
	}

	// 处理数字或字符串形式的时间戳
	let timestamp : number | null = null;
	if (typeof value === 'number') {
		timestamp = value;
	} else if (number(value)) {
		timestamp = parseFloat(value);
	}

	// 如果是有效的时间戳，使用时间戳创建Date对象
	if (timestamp !== null) {
		return !isNaN(new Date(timestamp).getTime());
	}

	// 否则直接使用字符串创建Date对象
	return !/Invalid|NaN/.test(new Date(value).toString());
}

/**
 * 验证ISO类型的日期格式（YYYY-MM-DD 或 YYYY/MM/DD）
 * @param value 待验证的日期字符串
 * @returns 是否符合ISO日期格式
 */
function dateISO(value : string) : boolean {
	return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value);
}

/**
 * 验证十进制数字
 * @param value 待验证的数字（字符串或数值）
 * @returns 是否为十进制数字
 */
function number(value : string | number) : boolean {
	return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(String(value));
}

/**
 * 验证是否为字符串类型
 * @param value 待验证的值
 * @returns 是否为字符串
 */
function string(value : unknown) : value is string {
	return typeof value === 'string';
}

/**
 * 验证整数
 * @param value 待验证的整数（字符串或数值）
 * @returns 是否为整数
 */
function digits(value : string | number) : boolean {
	return /^\d+$/.test(String(value));
}

/**
 * 验证身份证号码
 * @param value 待验证的身份证号字符串
 * @returns 是否符合身份证号格式
 */
function idCard(value : string) : boolean {
	return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value);
}

/**
 * 验证车牌号
 * @param value 待验证的车牌号字符串
 * @returns 是否符合车牌号格式
 */
function carNo(value : string) : boolean {
	// 新能源车牌
	const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
	// 旧车牌
	const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;

	if (value.length === 7) {
		return creg.test(value);
	} else if (value.length === 8) {
		return xreg.test(value);
	}
	return false;
}

/**
 * 验证金额格式（只允许2位小数）
 * @param value 待验证的金额（字符串或数值）
 * @returns 是否符合金额格式
 */
function amount(value : string | number) : boolean {
	return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(String(value));
}

/**
 * 验证是否为纯中文
 * @param value 待验证的字符串
 * @returns 是否为纯中文
 */
function chinese(value : string) : boolean {
	const reg = /^[\u4e00-\u9fa5]+$/gi;
	return reg.test(value);
}

/**
 * 验证是否只包含字母
 * @param value 待验证的字符串
 * @returns 是否只包含字母
 */
function letter(value : string) : boolean {
	return /^[a-zA-Z]*$/.test(value);
}

/**
 * 验证是否只包含字母或数字
 * @param value 待验证的字符串
 * @returns 是否只包含字母或数字
 */
function enOrNum(value : string) : boolean {
	const reg = /^[0-9a-zA-Z]*$/g;
	return reg.test(value);
}

/**
 * 验证一个值是否包含指定子串
 * @param value 源字符串
 * @param param 待检测的子串
 * @returns 是否包含子串
 */
function contains(value : string, param : string) : boolean {
	return value.indexOf(param) >= 0;
}

/**
 * 验证一个值是否在指定范围内 [min, max]
 * @param value 待验证的数值
 * @param param 范围数组 [min, max]
 * @returns 是否在范围内
 */
function range(value : number, param : [number, number]) : boolean {
	return value >= param[0] && value <= param[1];
}

/**
 * 验证字符串长度是否在指定范围内 [min, max]
 * @param value 待验证的字符串
 * @param param 长度范围数组 [min, max]
 * @returns 长度是否在范围内
 */
function rangeLength(value : string, param : [number, number]) : boolean {
	return value.length >= param[0] && value.length <= param[1];
}

/**
 * 验证是否为固定电话
 * @param value 待验证的固定电话字符串
 * @returns 是否符合固定电话格式
 */
function landline(value : string) : boolean {
	const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/;
	return reg.test(value);
}

/**
 * 判断值是否为空
 * @param value 待验证的值
 * @returns 是否为空
 */
function empty(value : unknown) : boolean {
	switch (typeof value) {
		case 'undefined':
			return true;
		case 'string':
			return value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length === 0;
		case 'boolean':
			return !value;
		case 'number':
			return value === 0 || isNaN(value);
		case 'object':
			if (value === null) return true;
			if (Array.isArray(value)) return value.length === 0;
			for (const i in value as object) {
				return false;
			}
			return true;
		default:
			return false;
	}
}

/**
 * 验证是否为JSON字符串
 * @param value 待验证的字符串
 * @returns 是否为JSON字符串
 */
function jsonString(value : string) : boolean {
	if (typeof value !== 'string') return false;
	try {
		const obj = JSON.parse(value);
		return typeof obj === 'object' && obj !== null;
	} catch (e) {
		return false;
	}
}

/**
 * 验证是否为数组
 * @param value 待验证的值
 * @returns 是否为数组
 */
function array(value : unknown) : value is unknown[] {
	if (typeof Array.isArray === 'function') {
		return Array.isArray(value);
	}
	return Object.prototype.toString.call(value) === '[object Array]';
}

/**
 * 验证是否为纯对象（排除数组、null等）
 * @param value 待验证的值
 * @returns 是否为纯对象
 */
function object(value : unknown) : value is Record<string, unknown> {
	return Object.prototype.toString.call(value) === '[object Object]';
}

/**
 * 验证是否为短信验证码（默认6位数字）
 * @param value 待验证的验证码字符串
 * @param len 验证码长度，默认6
 * @returns 是否符合验证码格式
 */
function code(value : string, len : number = 6) : boolean {
	return new RegExp(`^\\d{${len}}$`).test(value);
}

/**
 * 验证是否为函数
 * @param value 待验证的值
 * @returns 是否为函数
 */
function func(value : unknown) : value is (...args : unknown[]) => unknown {
	return typeof value === 'function';
}

/**
 * 验证是否为Promise对象
 * @param value 待验证的值
 * @returns 是否为Promise对象
 */
function promise(value : unknown) : value is Promise<unknown> {
	// 先检查是否为对象且不为null
	if (value === null || typeof value !== 'object') {
		return false;
	}

	// 检查是否有then、catch方法且它们都是函数
	const promiseLike = value as Promise<unknown>;
	return func(promiseLike.then) && func(promiseLike.catch);
}

/**
 * 验证是否为图片格式
 * @param value 待验证的图片路径或文件名
 * @returns 是否为图片格式
 */
function image(value : string) : boolean {
	const newValue = value.split('?')[0];
	const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
	return IMAGE_REGEXP.test(newValue);
}

/**
 * 验证是否为视频格式
 * @param value 待验证的视频路径或文件名
 * @returns 是否为视频格式
 */
function video(value : string) : boolean {
	const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i;
	return VIDEO_REGEXP.test(value);
}

/**
 * 验证是否为正则对象
 * @param o 待验证的值
 * @returns 是否为正则对象
 */
function regExp(o : unknown) : o is RegExp {
	return o !== null && Object.prototype.toString.call(o) === '[object RegExp]';
}

export default {
	email,
	mobile,
	url,
	date,
	dateISO,
	number,
	digits,
	idCard,
	carNo,
	amount,
	chinese,
	letter,
	enOrNum,
	contains,
	range,
	rangeLength,
	empty,
	isEmpty: empty,
	jsonString,
	landline,
	object,
	array,
	code,
	func,
	promise,
	video,
	image,
	regExp,
	string
};